#include <stdio.h>
#include <time.h>
#include <string.h>
#include <curl/curl.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>  
#include <openssl/bio.h>  
#include <openssl/evp.h>  
#include <openssl/buffer.h>
#include <jansson.h>  
  
// 将字节序列转换为 Base64 编码的字符串
char *base64_encode(const unsigned char *data, int data_len) {
    BIO *bio, *b64;
    BUF_MEM *bufferPtr;
    bio = BIO_new(BIO_s_mem());
    b64 = BIO_new(BIO_f_base64());
    bio = BIO_push(b64, bio);
    BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
    BIO_write(bio, data, data_len);
    BIO_flush(bio);
    BIO_get_mem_ptr(bio, &bufferPtr);
    BIO_set_close(bio, BIO_NOCLOSE);

    if (!bufferPtr) {
        fprintf(stderr, "Error getting buffer pointer\n");
        BIO_free_all(bio);
        return NULL;
    }

    char *encoded_data = (char *)malloc(bufferPtr->length + 1);
    if (!encoded_data) {
        fprintf(stderr, "Error allocating memory\n");
        BIO_free_all(bio);
        return NULL;
    }

    memcpy(encoded_data, bufferPtr->data, bufferPtr->length);
    encoded_data[bufferPtr->length] = '\0';
    BIO_free_all(bio);
    return encoded_data;
}

// 回调函数，用于接收服务器响应的数据
size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userdata) {
    size_t total_size = size * nmemb;
    char *response = (char *)userdata;
    
    // 将接收到的数据拼接到缓冲区中
    strncat(response, (char *)ptr, total_size);
    
    return total_size;
}

// 将字节序列转换为十六进制字符串表示
void bytes_to_hex(const unsigned char *bytes, size_t len, char *hex) {
    const char *hex_chars = "0123456789abcdef";
    for (size_t i = 0; i < len; i++) {
        hex[i * 2] = hex_chars[(bytes[i] >> 4) & 0x0F];
        hex[i * 2 + 1] = hex_chars[bytes[i] & 0x0F];
    }
    hex[len * 2] = '\0';
}

int main() {
    const char *version = "2022-05-01";
    const char *resourceName = "products/K7z0ZfElTn";
    long expirationTime = time(NULL) + 100 * 24 * 60 * 60;
    // long expirationTime = 1711208323;
    const char *signatureMethod = "sha1";
    const char *accessKey = "18+JK3n7Byf9nb3VZ9ProY+Fh+27J7c9Batvqxkh320=";
    // const char *key = "cmg2czRSYkJGS2dPcGtqNGR2bUhyTXJydFNhSlNoRXU=";

    // 构造待签名的字符串
    char to_sign[1024];
    snprintf(to_sign, sizeof(to_sign), "%ld\n%s\n%s\n%s", expirationTime, signatureMethod, resourceName, version);
    printf("to sign text is %s, length is %d\n", to_sign, strlen(to_sign));

    // 计算key
    BIO *bio = BIO_new(BIO_s_mem());
    BIO_puts(bio, accessKey);
    BIO *b64 = BIO_new(BIO_f_base64());
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
    bio = BIO_push(b64, bio);
    
    // 计算解码后的字节长度
    size_t decoded_len = strlen(accessKey) * 3 / 4 - 1;
    unsigned char *decoded_data = (unsigned char *)malloc(decoded_len);
    
    // 解码
    int decoded_size = BIO_read(bio, decoded_data, decoded_len);
    if (decoded_size < 0) {
        fprintf(stderr, "Error decoding Base64\n");
        return 1;
    }
    BIO_free_all(bio);

    printf("key is ");
    for (size_t i = 0; i < decoded_len; ++i) {
        printf("%02X", decoded_data[i]);
    }
    printf("\n");

    // 计算 Hmac
    unsigned int bytes_len;
    HMAC_CTX ctx;
    unsigned char *bytes = (unsigned char *)malloc(EVP_MAX_MD_SIZE);
    HMAC_CTX_init(&ctx);
    HMAC_Init_ex(&ctx, decoded_data, decoded_len, EVP_sha1(), NULL);
    HMAC_Update(&ctx, (unsigned char *)to_sign, strlen(to_sign));
    HMAC_Final(&ctx, bytes, &bytes_len);
    HMAC_CTX_cleanup(&ctx);

    printf("bytes is : ");
    for (size_t i = 0; i < bytes_len; ++i) {
        printf("%02X", bytes[i]);
    }
    printf("\n");

    // 对 Hmac 结果进行 Base64 编码
    char *signature = base64_encode(bytes, strlen(bytes));
    printf("====%s\n", signature);
    // 组装令牌字符串
    char token[2048];
    snprintf(token, sizeof(token), "version=%s&res=%s&et=%ld&method=%s&sign=%s", version, resourceName, expirationTime, signatureMethod, signature);

    // 输出令牌字符串
    printf("Authorization: %s\n", token);

    // 释放内存
    free(signature);
    free(bytes);

    char signature_str[1024];
    sprintf(signature_str, "authorization: %s", token);

    CURL *curl;
    CURLcode res;

    struct curl_slist *headers = NULL;

    // 初始化libcurl
    curl = curl_easy_init();
    if (!curl) {
        fprintf(stderr, "Failed to initialize libcurl\n");
        return 1;
    }

    // 设置要访问的URL
    curl_easy_setopt(curl, CURLOPT_URL, "https://iot-api.heclouds.com/datapoint/current-datapoints?product_id=K7z0ZfElTn&device_name=865377069214837");

    // 设置要使用的SSL/TLS版本
    // curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);

    // 设置 SSL 选项
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

    // 设置请求头
    headers = curl_slist_append(headers, "Accept: application/json, text/plain, */*");
    headers = curl_slist_append(headers, signature_str);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

    struct curl_slist *temp = headers;
    while (temp) {
        printf("%s\n", temp->data);
        temp = temp->next;
    }

    char response[10240] = {0};
    long response_code = 0;
    // 设置回调函数，接收服务器响应的数据
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
    // 设置接收服务器响应的字符串
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, response);
    // 设置接收服务器响应的状态码
    // curl_easy_setopt(curl, CURLOPT_RESPONSE_CODE, &response_code);

    // 发送POST请求
    res = curl_easy_perform(curl);
    if (res != CURLE_OK) {
        fprintf(stderr, "Failed to perform GET request: %s\n", curl_easy_strerror(res));
        curl_easy_cleanup(curl);
        return 1;
    }
    printf("response is : %s\n", response);

    json_error_t error;
    json_t *root = json_loads(response, 0, &error);
    if (!root) {
        printf("parse json error.\n");
    } else {
        printf("111\n");
        json_t *data = json_object_get(root, "data");
        if (json_is_object(data)) {
            printf("222\n");
            json_t *devices = json_object_get(data, "devices");
            if (json_is_array(devices)) {
                printf("333\n");
                json_t *device = json_array_get(devices, 0);
                if (json_is_object(device)) {
                    printf("444\n");
                    json_t *datastreams = json_object_get(device, "datastreams");
                    if (json_is_array(datastreams)) {
                        json_t *datastream = json_array_get(datastreams, 0);
                        if (json_is_object(datastream)) {
                            json_t *value = json_object_get(datastream, "value");
                            if (json_is_string(value)) {
                                printf("555\n");
                                printf("value is %s", json_string_value(value));
                            }
                        }
                    } 
                }
            }
        }

        json_decref(root);
    }

    // 清理并释放libcurl资源
    curl_easy_cleanup(curl);

    return 0;
}

